import copy
from qturboframe.lib.webdriver.exceptions import SeleniumError
from BladeFerm.Lib.Common import logger
from BladeFerm.hui_app.hui_lib.tree_grid import TreeGrid as HuiTreeGrid
from qturboframe.public_ui.base_element import BaseElement
from qturboframe.lib.webdriver.remote.webelement import WebElement
from .base_table import BaseTable
import time

class TreeGrid(HuiTreeGrid):
    '''
    对操作员中心特有的树形表格固定栏操作进行封装

    :Attributes:
     - _fixed_div: 当前表格中固定栏元素

    '''

    _fixed_div = WebElement
    
    def __init__(self, element_para, father=None, timeout=5):
        time.sleep(0.1)
        super().__init__(element_para, father, timeout)
        # self.head_table = BaseTable(
        #     {'xpath': './div/div[@class=\'h-editgird-header\']/table'}, self._element, self.timeout)
        # self.body_table = BaseTable(
        #     {'xpath': './div/div[@class=\'h-editgird-body\']/table'}, self._element, self.timeout)
        self.fixed()

    def fixed(self, idname=None, father=None):
        '''
        获取表格固定栏

        :Args:
         - idname: 固定栏的定位条件，字典类型：{'元素查找方式':'元素查找语句', '辅助属性':'辅助属性值'}
         - father: 固定栏的祖先级元素，可以给固定栏查找限定范围，默认为表格元素

        :Returns:
            返回固定栏对象，固定栏不存在则返回None

        :Example:
         - 例: table.fixed({'xpath':'./div/div[@class="h-table-fixed"]'})
        '''
        if father is None:
            father = self.element
        if idname:
            try:
                self._fixed_div = BaseElement(idname, father, timeout=0.1).element
            except SeleniumError:
                self._fixed_div = None
        else:
            self._fixed_div = father.exist('xpath', './div/div[@class=\'h-editgird-fixed\']', timeout=0.1)
            if not self._fixed_div:
                self._fixed_div = father.exist('xpath', './div/div[@class=\'h-editgird-fixed-right\']', timeout=0.1)
        return self._fixed_div

    def sidebar_btn(self, table_value, title_name, operate_name):
        '''
        获取表格侧边栏按钮对象

        :Args:
         - table_value: 勾选树节点的节点值
         - title_name: 查找的单元格列名
         - operate_name: 侧边栏按钮的名称

        :Returns:
            返回表格侧边栏按钮对象
        '''
        # 获取对应单元格对象
        cell = self.get_cell_side(table_value, title_name)
        if operate_name in ['权限复制', '绑定三方用户']:
            hidden_btn = cell.find_element_by_attribute('css selector', 'div.h-dropdown-rel span', 'text:...', timeout=0.1)
            hidden_btn.click()
            operate_btn = self._driver.find_element_by_attribute('css selector', 'div.h-select-dropdown ul.h-dropdown-menu li[title={}]'.format(operate_name), 'text:{}'.format(operate_name), timeout=self.timeout)
            ActionChains(self._driver).move_to_element(operate_btn)
            logger.debug('数据进行的操作: {}'.format(operate_name))
        else:
            operate_btn = cell.exist('css selector', 'span[style="display: initial;"]', 'text:{}'.format(operate_name), timeout=0.1)
            if not operate_btn:
                operate_btn = cell.find_element_by_attribute('css selector', 'span', 'text:{}'.format(operate_name), timeout=self.timeout)
            logger.debug('数据进行的操作: {}'.format(operate_name))
        return operate_btn

    def get_cell_text(self, tree_node, title_name):
        '''
        根据单元格列名和树表格节点查找树表格的单元格文本

        :Args:
         - tree_node: 树形结构顺序点击的节点值，例：'XX1/XX2/XX3'
         - title_name: 查找的单元格列名

        :Returns:
            返回查找的单元格

        :Example:
         - 例: cell = treegrid.get_cell_text('组织/部门/员工A', '工号')
        '''
        node_list = tree_node.split('/')
        node_title_list = None
        fixed_title_list = list()
        fixed_temp_table = None
        title_list = self.head_table.get_title_list()
        logger.debug('标题列表：{}'.format(title_list))
        temp_table = self.body_table
        # 查看是否存在冻结列
        if self._fixed_div:
            # 获取冻结列列名列表
            fixed_head_table = BaseTable(
                {'css selector': 'div.h-editgird-fixed-header>table'}, self._fixed_div, self.timeout)
            fixed_title_list = fixed_head_table.get_title_list()
            logger.debug('表格冻结列显示列名：' + str(fixed_title_list))
            fixed_temp_table = BaseTable({'css selector': 'div.h-editgird-fixed-body>table'}, self._fixed_div, self.timeout)
            node_title_list = fixed_title_list
            node_temp_table = fixed_temp_table
        else:
            node_title_list = title_list
            node_temp_table = temp_table
        title_lists, cell_lists = self.__get_cell(fixed_title_list, title_list, fixed_temp_table, temp_table)
        # 打开树枝表格
        if len(node_list) > 1:
            last_value = node_list[-1]
            del node_list[-1]
            for va in node_list:
                if title_name in title_lists:
                    title_index = title_lists.index(title_name)
                else:
                    raise SeleniumError('未找到对应的列名')
                if node_temp_table is not None:
                    title_lists, cell_lists = self.__get_cell(fixed_title_list, title_list, node_temp_table, temp_table)
                    up_table, up_title_table = self.__open_tree_tables(node_title_list, cell_lists, node_temp_table, va, title_index)
                    node_temp_table = up_table
                    temp_table = up_title_table
        else:
            last_value = node_list[0]
        row = self.__get_leaf_cell_row(node_title_list, node_temp_table, last_value)[1]
        cell = temp_table.element.find_elements_by_attribute('css selector', 'tr', timeout=self.timeout)[row - 1]
        cell_index = title_lists.index(title_name)
        title_td = cell.find_elements_by_attribute('css selector', 'td')[cell_index]
        text = title_td.find_element_by_attribute('css selector', 'span', timeout=self.timeout)
        return text

    def select_rows(self, tree_node_list):
        '''
        树表格行勾选
        重写说明：操作员中心树形表格的勾选节点在固定栏上，标准封装里直接在表格普通列上，封装做了涵盖

        :Args:
         - tree_node_list: 树形结构顺序点击的节点值列表，例：'XX1/XX2/XX3,XX1/XX4/XX5'

        :Example:
         - 例: treegrid.select_rows('根节点1/子节点1/叶子节点1,根节点2/子节点2/叶子节点2')
        '''
        re_choosed = 'h-checkbox-checked'
        if isinstance(tree_node_list, str):
            tree_node_list = tree_node_list.split(',')
        fixed_title_list = None
        # 查看是否存在冻结列
        if self._fixed_div:
            # 获取冻结列列名列表
            fixed_head_table = BaseTable(
                {'css selector': 'div.h-editgird-fixed-header>table'}, self._fixed_div, self.timeout)
            fixed_title_list = fixed_head_table.get_title_list()
            logger.debug('表格冻结列显示列名：' + str(fixed_title_list))
            fixed_temp_table = BaseTable({'css selector': 'div.h-editgird-fixed-body>table'}, self._fixed_div, self.timeout)
        title_list = self.head_table.get_title_list()
        logger.debug('标题列表：{}'.format(title_list))
        temp_table = self.body_table
        for tree_node in tree_node_list:
            if tree_node == '-':
                logger.debug('表格查询条件为空，不勾选！')
                return
            if fixed_title_list:
                node_title_list = fixed_title_list
                node_temp_table = fixed_temp_table
            else:
                node_title_list = title_list
                node_temp_table = temp_table
            node_list = tree_node.split('/')
            # 打开树枝表格
            if len(node_list) > 1:
                last_value = node_list[-1]
                del node_list[-1]
                for va in node_list:
                    if node_temp_table is not None:
                        up_table = self.__open_fixed_table(node_title_list, node_temp_table, va)
                        node_temp_table = up_table
            else:
                last_value = node_list[0]
            # 获取树叶节点单元格和行数
            cell, row = self.__get_leaf_cell_row(node_title_list, node_temp_table, last_value)
            # 节点勾选
            span = cell.find_element_by_attribute(
                'css selector', 'label.h-checkbox-wrapper>span.h-checkbox', timeout=self.timeout)
            if re_choosed not in span.get_attribute('class').split(' '):
                span.secure_click()
                
    def check_rows_exist(self, tree_node_list):
        '''
        根据树表格节点检查树表格行是否存在
        重写说明：操作员中心树形表格的勾选节点在固定栏上，标准封装里直接在表格普通列上，封装做了涵盖

        :Args:
         - tree_node_list: 树形结构顺序点击的节点值列表，例：['XX1/XX2/XX3', 'XX1/XX4/XX5']

        :Example:
         - 例: treegrid.select_rows(['根节点1/子节点1/叶子节点1','根节点2/子节点2/叶子节点2'])
        '''
        if isinstance(tree_node_list, str):
            tree_node_list = tree_node_list.split(',')
        fixed_title_list = None
        # 查看是否存在冻结列
        if self._fixed_div:
            # 获取冻结列列名列表
            fixed_head_table = BaseTable(
                {'css selector': 'div.h-editgird-fixed-header>table'}, self._fixed_div, self.timeout)
            fixed_title_list = fixed_head_table.get_title_list()
            logger.debug('表格冻结列显示列名：' + str(fixed_title_list))
            fixed_temp_table = BaseTable({'css selector': 'div.h-editgird-fixed-body>table'}, self._fixed_div,
                                         self.timeout)
        title_list = self.head_table.get_title_list()
        logger.debug('标题列表：{}'.format(title_list))
        temp_table = self.body_table
        for tree_node in tree_node_list:
            if tree_node == '-':
                logger.debug('表格查询条件为空，不勾选！')
                return
            if fixed_title_list:
                node_title_list = fixed_title_list
                node_temp_table = fixed_temp_table
            else:
                node_title_list = title_list
                node_temp_table = temp_table
            node_list = tree_node.split('/')
            # 打开树枝表格
            if len(node_list) > 1:
                last_value = node_list[-1]
                del node_list[-1]
                for va in node_list:
                    if node_temp_table is not None:
                        up_table = self.__open_fixed_table(node_title_list, node_temp_table, va)
                        node_temp_table = up_table
            else:
                last_value = node_list[0]
            # 获取树叶节点单元格和行数
            cell, row = self.__get_leaf_cell_row(node_title_list, node_temp_table, last_value)
            if not cell:
                raise SeleniumError('未找到 {} 节点，表格行校验不通过！'.format(last_value))

    def get_cell_side(self, tree_node, title_name):
        '''
        根据单元格列名和树表格节点查找树表格的单元格(该方法适用于固定栏为'操作'的表格)

        :Args:
         - tree_node: 树形结构顺序点击的节点值，例：'XX1/XX2/XX3'
         - title_name: 查找的单元格列名

        :Returns:
            返回查找的单元格

        :Example:
         - 例: cell = treegrid.get_cell('组织/部门/员工A', '工号')
        '''
        node_list = tree_node.split('/')
        len_node = len(node_list)
        node_title_list = None
        fixed_title_list = list()
        fixed_temp_table = None
        title_list = self.head_table.get_title_list()
        logger.debug('标题列表：{}'.format(title_list))
        temp_table = self.body_table
        # 查看是否存在冻结列
        if self._fixed_div:
            # 获取冻结列列名列表
            fixed_head_table = BaseTable(
                {'css selector': 'div.h-editgird-fixed-header>table'}, self._fixed_div, self.timeout)
            fixed_title_list = fixed_head_table.get_title_list()
            logger.debug('表格冻结列显示列名：' + str(fixed_title_list))
            fixed_temp_table = BaseTable({'css selector': 'div.h-editgird-fixed-body>table'}, self._fixed_div, self.timeout)
            node_title_list = fixed_title_list
            node_temp_table = fixed_temp_table
        else:
            node_title_list = title_list
            node_temp_table = temp_table
        title_lists, cell_lists = self.__get_cell(fixed_title_list, title_list, fixed_temp_table, temp_table)
        # 打开树枝表格
        if len(node_list) > 1:
            last_value = node_list[-1]
            del node_list[-1]
            for va in node_list:
                if title_name in title_lists:
                    title_index = title_lists.index(title_name)
                else:
                    raise SeleniumError('未找到对应的列名')
                if node_temp_table is not None:
                    title_lists, cell_lists = self.__get_cell(fixed_title_list, title_list, node_temp_table, temp_table)
                    up_table, up_title_table = self.__open_tree_tables(title_list, cell_lists, temp_table, va, title_index)
                    node_temp_table = up_table
                    temp_table = up_title_table
        else:
            last_value = node_list[0]
        if len_node > 1:
            title_lists, cell_lists = self.__get_cell(fixed_title_list, title_list, temp_table, node_temp_table)
        row = self.__get_leaf_cell_row(title_list, temp_table, last_value)[1]
        cell_index = title_lists.index(title_name)
        index = len(title_lists) * (row - 1) + cell_index
        title_td = cell_lists[index]
        return title_td

    def select_normal_rows(self, tree_node_list):
        '''
        操作员中心常规树表格行勾选

        :Args:
         - tree_node_list: 树形结构顺序点击的节点值列表，例：['XX1/XX2/XX3', 'XX1/XX4/XX5']

        :Example:
         - 例: treegrid.select_rows(['根节点1/子节点1/叶子节点1','根节点2/子节点2/叶子节点2'])
        '''
        re_choosed = 'h-checkbox-checked'
        if isinstance(tree_node_list, str):
            tree_node_list = tree_node_list.split(',')
        for tree_node in tree_node_list:
            if tree_node == '-':
                continue
            node_list = tree_node.strip().split('/')
            title_list = self.head_table.get_title_list()
            # 打开树枝表格
            if len(node_list) > 1:
                last_value = node_list[-1]
                del node_list[-1]
                temp_table = self.body_table
                for va in node_list:
                    if temp_table is not None:
                        up_table = self.__open_tree_table(title_list, temp_table, va)
                        temp_table = up_table
            else:
                temp_table = self.body_table
                last_value = node_list[0]
            # 获取树叶节点单元格
            cell = self.__get_leaf_cell(title_list, temp_table, last_value)
            # 节点勾选
            span = cell.find_element_by_attribute(
                'css selector', 'label.h-checkbox-wrapper>span.h-checkbox', timeout=self.timeout)
            if re_choosed not in span.get_attribute('class').split(' '):
                span.secure_click()

    def __open_fixed_table(self, title_list, node_table:BaseTable, node_name):
        # 固定栏勾选栏打开
        re_open = 'h-editgird-icon-click-expanded'
        node_cell_list = node_table.get_cell_list(len(title_list), 1)
        for cell in node_cell_list:
            if cell.text == node_name:
                logger.debug('打开节点：' + node_name)
                click_i = cell.find_element_by_attribute(
                    'css selector', 'i.h-editgird-icon-click', timeout=self.timeout)
                if re_open not in click_i.get_attribute('class').split(' '):
                    click_i.secure_click()
                next_tr = cell.find_elements_by_attribute(
                    'xpath', './parent::tr/following-sibling::tr', timeout=self.timeout)[0]
                next_table = next_tr.find_element_by_attribute('xpath', './td/table', timeout=self.timeout)
                return BaseTable(next_table)
        else:
            raise SeleniumError('未找到 {} 节点！'.format(node_name))

    def __open_tree_tables(self, title_list, cell_list, node_table:BaseTable, node_name, node_index):
        re_open = 'h-editgird-icon-click-expanded'
        node_cell_list = node_table.get_cell_list(len(title_list), 1)
        row = 0
        for cell in node_cell_list:
            if cell.text == node_name:
                logger.debug('打开节点：' + node_name)
                click_i = cell.find_element_by_attribute(
                    'css selector', 'i.h-editgird-icon-click', timeout=self.timeout)
                if re_open not in click_i.get_attribute('class').split(' '):
                    click_i.secure_click()
                # 节点打开过慢，暂时加0.5秒等待
                # time.sleep(0.5)
                next_tr = cell.find_elements_by_attribute(
                    'xpath', './parent::tr/following-sibling::tr', timeout=self.timeout)[0]
                next_table = next_tr.find_element_by_attribute('xpath', './td/table', timeout=self.timeout)
                next_title_tr = cell_list[row + node_index].find_elements_by_attribute(
                    'xpath', './parent::tr/following-sibling::tr', timeout=self.timeout)[row]
                next_title_table = next_title_tr.find_element_by_attribute('xpath', './td/table', timeout=self.timeout)
                return BaseTable(next_table), BaseTable(next_title_table)
            row += 1
        else:
            raise SeleniumError('未找到 {} 节点！'.format(node_name))

    def __get_leaf_cell_row(self, title_list, node_table:BaseTable, node_name):
        node_cell_list = node_table.get_cell_list(len(title_list), 1)
        row = 0
        for cell in node_cell_list:
            row += 1
            if cell.text == node_name:
                logger.debug('查找到节点：' + node_name)
                return cell, row
        else:
            return None, row

    def __get_cell(self, fixed_title_list, title_list, fixed_body_table, body_table):
        table_cell = None
        fixed_cell_list = list()
        # 查看是否存在冻结列
        if fixed_title_list:
            fixed_cell_list = fixed_body_table.get_cell_list()
        # 获取数据表格单元格列表
        cell_list = body_table.get_cell_list()
        # 组合冻结列与非冻结列
        temp_title_list, temp_cell_list = self.__join_list(
            fixed_title_list, title_list, fixed_cell_list, cell_list)
        return temp_title_list, temp_cell_list

    def __join_list(self, tlist1, tlist2, list1, list2):
        templist2 = list()
        for i in range(0, int((len(list1) + len(list2)) / (len(tlist1) + len(tlist2)))):
            for j in range(0, len(tlist1)):
                templist2.append(list1[int(i * len(tlist1) + j)])
            for j in range(0, len(tlist2)):
                templist2.append(list2[int(i * len(tlist2) + j)])
        templist1 = copy.deepcopy(tlist1)
        templist1.extend(tlist2)
        return templist1,templist2

    def __open_tree_fix(self, title_list, node_table:BaseTable, node_name):
        re_open = 'h-editgird-icon-click-expanded'
        node_cell_list = node_table.get_cell_list(len(title_list), 1)
        for cell in node_cell_list:
            if cell.text == node_name:
                logger.debug('打开节点：' + node_name)
                click_i = cell.find_element_by_attribute(
                    'css selector', 'i.h-editgird-icon-click', timeout=self.timeout)
                if re_open not in click_i.get_attribute('class').split(' '):
                    click_i.secure_click()
                next_tr = cell.find_elements_by_attribute(
                    'xpath', './parent::tr/following-sibling::tr', timeout=self.timeout)[0]
                next_table = next_tr.find_element_by_attribute('xpath', './td/table', timeout=self.timeout)
                return BaseTable(next_table)
        else:
            raise SeleniumError('未找到 {} 节点！'.format(node_name))
    